#coding:utf-8
import random
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from io import BytesIO

'''
    作用：使用PIL生成图片验证码
'''
class ValidCodeImg:
    def __init__(self, width=150, height=30, code_count=5, font_size=32, point_count=20, line_count=3, img_format='png'):
        '''
            作用：生成随机图片验证码
            :param width: 图片宽度 单位px
            :param height: 图片高度 单位px
            :param code_count: 验证码个数
            :param font_size: 字体大小
            :param point_count: 噪点个数
            :param line_count: 干扰线条数
            :param img_format: 生成的图片格式
            :return 生成的图片的bytes类型的data
        '''
        self.width = width
        self.height = height
        self.code_count = code_count
        self.font_size = font_size
        self.point_count = point_count
        self.line_count = line_count
        self.img_format = img_format
    
    def getRandomColor(self):
        '''
            作用：获取随机的(R,G,B)颜色值
        '''
        r = random.randint(0, 255)
        g = random.randint(0, 255)
        b = random.randint(0, 255)
        return (r,g,b)
    
    def getRandomStr(self):
        '''
            作用：获取随机的字符串:数字、小写字母、大写字母
            :return 返回随机的字符
        '''
        random_num = str(random.randint(0, 9))
        random_low_alpha = chr(random.randint(97, 122))
        random_upper_alpha = chr(random.randint(65, 90))
        random_char = random.choice([random_num, random_low_alpha, random_upper_alpha])
        return random_char
    
    def getValidCodeImg(self):
        '''
            作用：获取验证码图片，以及验证码正确值
            :return 验证码图片、验证码字符串值
        '''
        #获取一个Image对象，参数分别是RGB模式。宽150,高30,随机颜色
        image = Image.new('RGB', (self.width, self.height), self.getRandomColor())

        #获取画笔对象，并把图片对象传进去
        draw = ImageDraw.Draw(image)

        #获取一个font字体对象，参数是ttf的字体目录，以及字体的大小
        font = ImageFont.truetype('/usr/share/fonts/nakula.ttf', size=self.font_size)

        #储存随机字符
        temp = []
        #循环并获取验证码个数
        for i in range(self.code_count):
            #获取验证码字符
            random_char = self.getRandomStr()
             #储存随机字符,供验证时使用
            temp.append(random_char)

            #在图片上依次写入得到的随机字符，参数为：位置、字符串、颜色、字体
            draw.text((5 + i*30, -15), random_char, self.getRandomColor(), font=font)

        #验证码字符串值
        valid_str = ''.join(temp)

        #画干扰线,参数为：起点的x/y、结束点的x/y、填充颜色值
        for i in range(self.line_count):
            x1 = random.randint(0, self.width)
            y1 = random.randint(0, self.height)

            x2 = random.randint(0, self.width)
            y2 = random.randint(0, self.height)

            draw.line((x1, y1, x2, y2), fill=self.getRandomColor())

        #画干扰噪点
        for i in range(self.point_count):
            #画点，参数为：点的位置（x、y）、填充色
            x = random.randint(0, self.width)
            y = random.randint(0, self.height)
            draw.point([x, y], fill=self.getRandomColor())
            #根据点画圆，参数为：左上角坐标，右下角坐标，起始弧度，结束弧度，颜色
            draw.arc([x, y, x+4, y+4], 0, 90, fill=self.getRandomColor())

        #在内存内生成图片
        f = BytesIO()
        image.save(f, self.img_format)
        data = f.getvalue()
        f.close()

        #返回结果
        return data, valid_str


if __name__ == "__main__":
    img = ValidCodeImg()
    data, valid_str = img.getValidCodeImg()
    print(valid_str)

    with open('test.png', 'wb') as f:
        f.write(data)